#coding=UTF-8

import os
import HTMLParser
import urllib2

gHeaders = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11',
    'Accept-Charset':'GBK,utf-8;q=0.7,*;q=0.3',
    'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4',
    'Referer': 'http://book.douban.com/subject/6709783/',
    'Cookie': 'bid="RHgr1sKjoKs"; viewed="5286821_3771562_3012601"; dbcl2="50247020:KqoxerO+8iA"; ck="ugP6"; __utma=30149280.398045365.1344069602.1357548989.1357554463.36; __utmb=30149280.3.10.1357554463; __utmc=30149280; __utmz=30149280.1357538733.33.29.utmcsr=baidu|utmccn=(organic)|utmcmd=organic|utmctr=douban%20api; __utmv=30149280.5024; __utma=81379588.670245987.1355719224.1357548989.1357554463.8; __utmb=81379588.3.10.1357554463; __utmc=81379588; __utmz=81379588.1357276075.4.4.utmcsr=baidu|utmccn=(organic)|utmcmd=organic|utmctr=%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98'
}

def fetchHtml(url, timeout):
    print('now_parsing@' + url)    
    req = urllib2.Request(url, headers=gHeaders)
    fp = urllib2.urlopen(req, None, timeout)
    html = fp.read()
    fp.close()
    return html
    
class DoubanBookRecParser(HTMLParser.HTMLParser):
    
    def __init__(self, ownUrl = None):
        HTMLParser.HTMLParser.__init__(self)
        self._stat = 0
        self._bookUrl = ''
        self._rec = {}

        
    def handle_starttag(self, tag, attrs):
        if len(attrs) == 0: pass
        
        if tag == 'div':
            for (k, v) in attrs:
                if k == 'id' and v == 'db-rec-section':
                    self._stat = 1
                    break;
            return
                     
        if tag == 'dd' and self._stat == 1:
            self._stat = 2
            return
                
        if tag == 'a' and self._stat == 2:
            self._stat = 3
            for (k, v) in attrs:
                if k == 'href':
                    self._bookUrl = v
                    break
            return
            
    def handle_endtag(self, tag):
        if self._stat > 1 and tag in ['dd', 'a']:
            self._stat = self._stat - 1
        
        if self._stat == 1 and tag == 'div':
            self._stat = 0
            
    def handle_data(self, data):
        if self._stat == 3:
            self._rec[data.strip()] = self._bookUrl.strip()
    
    def getData(self):
        return self._rec

class Book(object):
    def __init__(self, book, url):
        self._book = book
        self._url = url
        self._rlbooks = []
    
    def addR(self, b):
        if (b != None) and (b not in self._rlbooks):
            self._rlbooks.append(b)
    
    def relatedbook(self): return self._rlbooks
    def book(self): return self._book
    def url(self): return self._url
    def __hash__(self): return hash(self._url)
    def __eq__(self, other):
        if other == None: return False
        return self._url.lower() == other._url.lower()

def fetch(url):
    html = fetchHtml(url, 1000)
    parser = DoubanBookRecParser()
    parser.feed(unicode(html,'UTF-8'))
    parser.close()
    map = parser.getData()
    return map

def assemble(map, book):
    for (k, v) in map.items():
        book.addR(Book(k, v))
            
def recursiveVisit(book, depth):
    if depth > 2: return None
    assemble(fetch(book.url()), book)
    for b in book.relatedbook():
        recursiveVisit(b, depth + 1)
    return book
 
    
if __name__ == '__main__':
    
    books = recursiveVisit(Book('First', 'http://book.douban.com/subject/6021440/'), 1)

    for i in books.relatedbook():
        print('%s: %s, %d'%(i.book(), i.url(), len(i.relatedbook())))
        for ii in i.relatedbook():
            print('--> %s: %s'%(ii.book(), ii.url()))
        
    os.system('pause')
    